home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Found / FWCommon / Sources / FWThrdGd.cpp < prev   
Encoding:
Text File  |  1995-11-08  |  9.2 KB  |  313 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWThrdGd.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    (c) 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef FWTHRDGD_H
  13. #include "FWThrdGd.h"
  14. #endif
  15.  
  16. #ifndef FWPRIMEM_H
  17. #include "FWPriMem.h"
  18. #endif
  19.  
  20. #ifndef FWEXCDEF_H
  21. #include "FWExcDef.h"
  22. #endif
  23.  
  24. #ifdef FW_BUILD_MAC
  25. #pragma segment FWCommon
  26. #endif
  27.  
  28.  
  29. //=====================================================================================
  30. // Class FW_CThreadSafe
  31. //=====================================================================================
  32.  
  33. FW_CThreadGuard *FW_CThreadSafe::fgSwitchGuards = 0;
  34. FW_CThreadGuard *FW_CThreadSafe::fgTerminationGuards = 0;
  35.  
  36.  
  37. //------------------------------------------------------------------------------
  38. // FW_CThreadSafe::NoteCreation
  39. //
  40. // Register the creation of a thread.  This should be called from a critical
  41. // section.  All guards are on the list of termination guards.
  42. //------------------------------------------------------------------------------
  43. void FW_CThreadSafe::NoteCreation(FW_ThreadID newlyCreatedThread)
  44. {
  45. #ifdef    FW_BUILD_MAC
  46.     FW_CThreadGuard *aThreadGuard;
  47.  
  48.     for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  49.     {
  50.         // A throw in the middle of this would be bad.  Catch everything and ignore
  51.         // it.  We can't do much else (except assert, and that might also be deadly).
  52.         FW_TRY
  53.         {
  54.             // The "Created" method can call AddThreadInfo to associate a chunk of storage 
  55.             // with this thread.
  56.             aThreadGuard->Created(newlyCreatedThread);
  57.         }
  58.         FW_CATCH_BEGIN
  59.         FW_CATCH_EVERYTHING()
  60.         FW_CATCH_END
  61.     }
  62. #endif
  63. }
  64.  
  65.  
  66. //------------------------------------------------------------------------------
  67. // FW_CThreadSafe::NoteTermination
  68. //
  69. // Register the destruction of a thread.  This should be called from a critical
  70. // section
  71. //------------------------------------------------------------------------------
  72. void FW_CThreadSafe::NoteTermination(FW_ThreadID threadBeingKilled)
  73. {
  74. #ifdef    FW_BUILD_MAC
  75.     FW_CThreadGuard *aThreadGuard;
  76.  
  77.     for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  78.     {
  79.         FW_TRY
  80.         {
  81.             // The "Terminating" method can call DeleteThreadInfo to remove the association 
  82.             // of any information with this thread.  
  83.             aThreadGuard->Terminating(threadBeingKilled);
  84.         }
  85.         FW_CATCH_BEGIN
  86.         FW_CATCH_EVERYTHING()
  87.         FW_CATCH_END
  88.     }
  89. #endif
  90. }
  91.  
  92.  
  93. #ifdef    FW_BUILD_MAC
  94. //------------------------------------------------------------------------------
  95. // FW_CThreadSafe::NoteSwitch
  96. //
  97. // Called between threads, indicating which are the old and the new threads.
  98. // This should be called from a critical section.
  99. //------------------------------------------------------------------------------
  100. void FW_CThreadSafe::NoteSwitch(FW_ThreadID aThread, FW_Boolean switchingIn)
  101. {
  102.     FW_CThreadGuard *aThreadGuard;
  103.     unsigned long mask;
  104.     
  105.     if (switchingIn)
  106.         mask = FW_CThreadGuard::kSwitchInThreadEvent;
  107.     else
  108.         mask = FW_CThreadGuard::kSwitchOutThreadEvent;
  109.  
  110.     for (aThreadGuard = fgSwitchGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
  111.     {
  112.         FW_TRY
  113.         {
  114.             if (aThreadGuard->GetMask() & mask)
  115.                 aThreadGuard->Switch(aThread, switchingIn);
  116.         }
  117.         FW_CATCH_BEGIN
  118.         FW_CATCH_EVERYTHING()
  119.         FW_CATCH_END
  120.     }
  121. }
  122. #endif
  123.  
  124.  
  125. //------------------------------------------------------------------------------
  126. // FW_CThreadSafe::RegisterTerminationGuard
  127. //
  128. // Add a ThreadGuard to the list of guardians
  129. //------------------------------------------------------------------------------
  130. void FW_CThreadSafe::RegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
  131. {
  132.     // Add this guardian to the head of the list
  133.     aThreadGuard->fNext = fgTerminationGuards;
  134.     fgTerminationGuards = aThreadGuard;
  135. }
  136.  
  137.  
  138. //------------------------------------------------------------------------------
  139. // FW_CThreadSafe::DeRegisterTerminationGuard
  140. //
  141. // Remove a ThreadGuard from the list of guardians
  142. //------------------------------------------------------------------------------
  143. void FW_CThreadSafe::DeRegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
  144. {
  145.     // Remove from the head of the list.  Should be safe as destructors are 
  146.     // executed in reverse order from the constructors
  147.     if (fgTerminationGuards == aThreadGuard)
  148.         fgTerminationGuards = aThreadGuard->fNext;
  149. }
  150.  
  151.  
  152. //------------------------------------------------------------------------------
  153. // FW_CThreadSafe::RegisterSwitchGuard
  154. //
  155. // Add a ThreadGuard to the list of guardians
  156. //------------------------------------------------------------------------------
  157. void FW_CThreadSafe::RegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
  158. {
  159.     // Add this guardian to the head of the list
  160.     aThreadGuard->fNext = fgSwitchGuards;
  161.     fgSwitchGuards = aThreadGuard;
  162. }
  163.  
  164.  
  165. //------------------------------------------------------------------------------
  166. // FW_CThreadSafe::DeRegisterSwitchGuard
  167. //
  168. // Remove a ThreadGuard from the list of guardians
  169. //------------------------------------------------------------------------------
  170. void FW_CThreadSafe::DeRegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
  171. {
  172.     // Remove from the head of the list.  Should be safe as destructors are 
  173.     // executed in reverse order from the constructors
  174.     if (fgSwitchGuards == aThreadGuard)
  175.         fgSwitchGuards = aThreadGuard->fNext;
  176. }
  177.  
  178.  
  179. //=====================================================================================
  180. // Class FW_CThreadGuard
  181. //=====================================================================================
  182.  
  183. //------------------------------------------------------------------------------
  184. // FW_CThreadGuard::FW_CThreadGuard
  185. //
  186. // Constructor for FW_CThreadGuard
  187. //------------------------------------------------------------------------------
  188. FW_CThreadGuard::FW_CThreadGuard(unsigned long threadEventMask) :
  189.     fActiveThreads(0),
  190.     fMask(threadEventMask)
  191. {
  192.     // Always check for termination if checking for anything
  193.     if (threadEventMask != 0)
  194.         FW_CThreadSafe::RegisterTerminationGuard(this);
  195.  
  196.     if (threadEventMask & (kSwitchInThreadEvent | kSwitchOutThreadEvent))
  197.         FW_CThreadSafe::RegisterSwitchGuard(this);
  198. }
  199.  
  200.  
  201. //------------------------------------------------------------------------------
  202. // FW_CThreadGuard::~FW_CThreadGuard
  203. //
  204. // Destructor for FW_CThreadGuard
  205. //------------------------------------------------------------------------------
  206. FW_CThreadGuard::~FW_CThreadGuard()
  207. {
  208.     FW_CThreadSafe::DeRegisterTerminationGuard(this);
  209.     FW_CThreadSafe::DeRegisterSwitchGuard(this);
  210.  
  211.     while (fActiveThreads != 0)
  212.     {
  213.         FW_SThreadItem *anItem = fActiveThreads;
  214.  
  215.         fActiveThreads = anItem->fNext;
  216.         FW_PrimitiveFreeBlock(anItem);
  217.     }
  218. }
  219.  
  220.  
  221. #ifdef    FW_BUILD_MAC
  222. //------------------------------------------------------------------------------
  223. // FW_CThreadGuard::Switch
  224. //
  225. // Called between thread switches
  226. //------------------------------------------------------------------------------
  227. void FW_CThreadGuard::Switch(FW_ThreadID, FW_Boolean)
  228. {
  229.     // Default is to do nothing
  230. }
  231. #endif
  232.  
  233.  
  234. //------------------------------------------------------------------------------
  235. // FW_CThreadGuard::AddThreadInfo
  236. //
  237. // Associates a void* with a ThreadID.  
  238. //------------------------------------------------------------------------------
  239. void FW_CThreadGuard::AddThreadInfo(FW_ThreadID aThreadID, void *threadInfo)
  240. {
  241.     FW_SThreadItem *newItem = (FW_SThreadItem *)FW_PrimitiveAllocateBlock(sizeof(FW_SThreadItem));
  242.  
  243.     // [jkp] -- what's the approved method of suicide?
  244.     if (newItem != 0)
  245.     {
  246.         newItem->fThreadID = aThreadID;
  247.         newItem->fThreadInfo = threadInfo;
  248.  
  249.         newItem->fNext = fActiveThreads;
  250.         fActiveThreads = newItem;
  251.     }
  252. }
  253.  
  254.  
  255. //------------------------------------------------------------------------------
  256. // FW_CThreadGuard::GetThreadInfo
  257. //
  258. // Returns the void* with a ThreadID.  
  259. //------------------------------------------------------------------------------
  260.  
  261. void *FW_CThreadGuard::GetThreadInfo(FW_ThreadID aThreadID)
  262. {
  263.     for (FW_SThreadItem *anItem = fActiveThreads; anItem != 0; anItem = anItem->fNext)
  264.     {
  265.         if (anItem->fThreadID == aThreadID)
  266.             return anItem->fThreadInfo;
  267.     }
  268.  
  269.     // [jkp] -- what's the approved method of suicide?
  270.     return 0;
  271. }
  272.  
  273.  
  274. //------------------------------------------------------------------------------
  275. // FW_CThreadGuard::RemoveThreadInfo
  276. //
  277. // Removes the association between a ThreadID and any chunk of data it pointed
  278. // to.  The caller must destroy the chunk of data, we don't know how.
  279. //------------------------------------------------------------------------------
  280. void FW_CThreadGuard::RemoveThreadInfo(FW_ThreadID aThreadID)
  281. {
  282.     FW_SThreadItem **itemPtr = &fActiveThreads;
  283.     FW_SThreadItem *anItem = fActiveThreads;
  284.  
  285.     while (anItem != 0)
  286.     {
  287.         if (anItem->fThreadID == aThreadID)
  288.         {
  289.             *itemPtr = anItem->fNext;
  290.             FW_PrimitiveFreeBlock(anItem);
  291.             return;
  292.         }
  293.         itemPtr = &anItem->fNext;
  294.         anItem = anItem->fNext;
  295.     }
  296.     // [jkp] -- what's the approved method of suicide?
  297. }
  298.  
  299.  
  300. //------------------------------------------------------------------------------
  301. // FW_CThreadGuard::GetMask
  302. //------------------------------------------------------------------------------
  303. unsigned long FW_CThreadGuard::GetMask() const
  304. {
  305.     return fMask;
  306. }
  307.  
  308.  
  309. #if FW_LIB_EXPORT_PRAGMAS
  310. #pragma lib_export on
  311. #endif
  312.  
  313.